﻿
using System;
using System.Diagnostics.Contracts;

namespace MathService.Vectors
{
    public struct Basis2D
    {
        private static readonly Func<double, double> sin = Math.Sin;
        private static readonly Func<double, double> cos = Math.Cos;

        public static readonly Basis2D Evclid = new Basis2D(
            1, 0,
            0, 1);

        public static Basis2D Rotate(double Angle, bool Positive = true)
        {
            return new Basis2D(
                cos(Angle), (Positive ? -1 : 1) * sin(Angle),
                (Positive ? 1 : -1) * sin(Angle), cos(Angle));
        }

        public static Basis2D Scale(double kx, double ky)
        {
            return new Basis2D(
                kx, 0,
                0, ky);
        }

        private double f_xx;
        public double xx { get { return f_xx; } set { f_xx = value; } }

        private double f_xy;
        public double xy { get { return f_xy; } set { f_xy = value; } }

        private double f_yx;
        public double yx { get { return f_yx; } set { f_yx = value; } }

        private double f_yy;
        public double yy { get { return f_yy; } set { f_yy = value; } }

        public Basis2D(double xx, double xy, double yx, double yy)
        {
            f_xx = xx;
            f_xy = xy;
            f_yx = yx;
            f_yy = yy;
        }

        public static implicit operator Matrix(Basis2D b)
        {
            Contract.Ensures(Contract.Result<Matrix>().M == 2, "Число столбцов матрицы = 2");
            Contract.Ensures(Contract.Result<Matrix>().N == 2, "Число строк матрицы = 2");

            return new Matrix(new[,] { { b.f_xx, b.f_xy }, { b.f_yx, b.f_yy } });
        }

        public static explicit operator Basis2D(Matrix M)
        {
            Contract.Requires<ArgumentException>(M.M == 2 && M.N == 2, "Матрица должна быть размера 2х2");

            //if(M.M != 2 || M.N != 2)
            //    throw new ArgumentException("Матрица должна быть размера 2х2");
            //Contract.EndContractBlock();


            return new Basis2D(
                M[0, 0], M[0, 1],
                M[1, 0], M[1, 1]);
        }
    }
}
